﻿using System;
using System.Collections.Generic;
using System.Text;

namespace MP3SharpFix
{
    public class Mp3Data : IDisposable
    {
        System.IO.Stream stream;
        public Mp3Data(System.IO.Stream stream)
        {
            this.stream = stream;
            if (this.stream != null)
            {
                TryLoadHeader();
            }
        }
        public void GetAll()
        {
            while (ReadNext()!=null)
            {
                continue;
            }
        }

        public Mp3Frame GetFrame(int frameid)
        {
            if (frameid < frames.Count)
                return frames[frameid];
            else
                return null;
        }

        public Mp3Frame ReadNext()
        {
            while (true)
            {
                if (Mp3Reader.ReadHeaderInt(this.stream, out int headerInt))
                {
                    //var pos = stream.Position;
                    if (Mp3IDFrame.TryRead(stream, headerInt, out Mp3IDFrame idframe))
                    {
                        this.ids.Add(idframe);
                    }
                    else if (Mp3RiffFrame.TryRead(stream, headerInt, out Mp3RiffFrame riffFrame))
                    {

                    }
                    else if (Mp3Reader.ParseFrameHeader(stream, headerInt, out Mp3Frame frame, false, this.Channel == 1))//这是个无聊的检查, bfirst, single_ch_mode))
                    {
                        frame.ReadData(stream);
                        //frameid = frames.Count;
                        frames.Add(frame);
                        return frame;
                    }
                    else
                    {
                        //stream.Position = pos;
                        throw new Exception("can't read stream.");
                    }
                }
                else
                {
                    //frameid = 0;
                    Ended = true;
                    return null;
                }
            }

        }

        /// <summary>
        /// 文件头是否初始化
        /// </summary>
        public bool Inited
        {
            get;
            private set;
        }
        /// <summary>
        /// 是否已达frame尾部
        /// </summary>
        public bool Ended
        {
            get;
            private set;
        }
        public int Frequency
        {
            get
            {
                if (vbrInfo != null)
                    return vbrInfo.SampleRate;
                else
                    return frames[0].GetFrequency();
            }
        }
        public int Channel
        {
            get
            {
                if (vbrInfo != null)
                    return vbrInfo.Channels;
                else
                    return frames[0].h_mode == Mp3Reader.SINGLE_CHANNEL ? 1 : 2;
            }
        }
        public int SamplePerFrame
        {
            get
            {
                if (vbrInfo != null)
                    return vbrInfo.SampleCount;
                else
                    return frames[0].GetSampleCount();
            }
        }
        /// <summary>
        /// 总帧数
        /// </summary>
        public int TotalFrameCount
        {
            get
            {
                if (!Inited) return 0;
                if (vbrInfo != null)
                    return vbrInfo.VBRFrames;
                if (Ended)
                    return frames.Count;
                return 0;
            }
        }
        /// <summary>
        /// 已读采样数
        /// </summary>
        public int ReadFrameCount
        {
            get
            {
                return this.frames.Count;
            }
        }

        public float TotalTimer
        {
            get
            {
                return TotalFrameCount * SamplePerFrame / (float)Frequency;
            }
        }
        public float ReadTimer
        {
            get
            {
                return ReadFrameCount * SamplePerFrame / (float)Frequency;
            }
        }
        bool TryLoadHeader()
        {

            while (!Inited)
            {
                if (Mp3Reader.ReadHeaderInt(this.stream, out int headerInt))
                {
                    //var pos = stream.Position;
                    if (Mp3IDFrame.TryRead(stream, headerInt, out Mp3IDFrame idframe))
                    {
                        this.ids.Add(idframe);
                    }
                    else if (Mp3RiffFrame.TryRead(stream, headerInt, out Mp3RiffFrame riffFrame))
                    {

                    }
                    else if (Mp3Reader.ParseFrameHeader(stream, headerInt, out Mp3Frame frame, true, false))//这是个无聊的检查, bfirst, single_ch_mode))
                    {
                        frame.ReadData(stream);


                        this.vbrInfo = frame.ParseVBR();
                        //if (this.vbrInfo == null)
                        {
                            this.frames.Add(frame);
                            Inited = true;
                            return true;
                        }
                        //else
                        //{
                        //    if (Mp3Reader.ReadHeaderInt(this.stream, out int header))
                        //    {
                        //        if (Mp3Reader.ParseFrameHeader(stream, header, out Mp3Frame frame0))
                        //        {
                        //            frame0.ReadData(stream);
                        //            this.frames.Add(frame0);
                        //            Inited = true;
                        //            return true;
                        //        }
                        //    }

                        //    throw new Exception("error to got first frame.");

                        //}
                    }
                    else
                    {
                        //stream.Position = pos;
                        throw new Exception("can't read stream.");
                    }
                }
            }
            return false;
        }
        public void Dispose()
        {
            this.stream.Close();
        }
        private List<Mp3IDFrame> ids = new List<Mp3IDFrame>();
        private List<Mp3Frame> frames = new List<Mp3Frame>();
        private VBRInfo vbrInfo;

    }
}
